core.net = {};

core.net.inIndicator = 0;
core.net.messageID = 0;
core.net.acceptRequests = true;
core.net.disables = [];
core.net.disablesIndex = 0;
core.net.doInIndicator = function(){
    core.net.startInIndicator();
    core.setTimeout(core.net, core.net.stopInIndicator, 1000);
}

core.net.startInIndicator = function(){
    if(core.net.inIndicator==0){
        core.desktop.indicator.setIndicator(true);
    }
    core.net.inIndicator++;
}

core.net.stopInIndicator = function(){
    core.net.inIndicator--;
    if(core.net.inIndicator<=0){
        core.desktop.indicator.setIndicator(false);
    }
}

core.net.sendMessage = function(config){
    if(!core.net.acceptRequests)
        return;
    var message = {};
    message.app = config.app;
    message.dialog = config.dialog;
    message.frame = config.frame;
    message.method = config.method;
    message.message = config.message;
    message.token = core.net.token;
    if(config.disableMe){
        if(config.fullDisable){
            var dIndex = core.net.disablesIndex++;
            core.net.disables[dIndex] = config.disableMe;
//            core.log('fullDisable', message.method, dIndex);
            message.disableIndex = dIndex;
            message.fullDisable = true;
        }
        config.disableMe.markLoading();
    }
    core.net.startInIndicator();
    core.net.request('message?ts='+(new Date().getTime()), message, function(data){
        core.net.stopInIndicator();
        if(config.disableMe && !config.fullDisable)
            config.disableMe.unMarkLoading();
        var messageResult = data.message_result || {};
        if(messageResult.type=='error'){
            if(config.errorHandler)
                config.errorHandler(messageResult.errorCode, messageResult.errorDescription);
            else{
                if(config.application)
                    config.application.showError(messageResult.errorDescription);
            }
        }else{
            if(config.okHandler){
                config.okHandler(messageResult);
            }
        }
        var arr = $.makeArray(data.messages);
//        core.log('after sending message got new ', arr.length);
        core.net.processIncomingMessages(arr);
    }, function(p1, p2){
        core.net.stopInIndicator();
        if(config.disableMe)
            config.disableMe.unMarkLoading();
        if(config.errorHandler)
            config.errorHandler(p1, p2);
        else{
            if(config.application)
                config.application.showError(p2);
        }
    });
};


core.net.request = function(aType, aData, aOkHandler, aErrorHandler){
    if(!core.net.acceptRequests)
        return;
    var json = JSON.stringify(aData?aData:{});
//    core.log('Sending', json);
    $.ajax({
        cache: false,
        data: json,
        dataType: 'json',
        error: function(){
            if(aErrorHandler){
                aErrorHandler(0, 'Network error. There was an error sending message to server');
            }
        },
        success: function(data){
            if(data && data.type=='error'){
                if(aErrorHandler)
                    aErrorHandler(data.errorCode, data.errorDescription);
                return;
            }
            if(aOkHandler)
                aOkHandler(data);
        },
        contentType: 'application/json; charset=utf-8',
        type: 'POST',
        url: 'net/'+aType
    });
}

core.net.processIncomingMessages = function(arr){
    for (var i = 0; i < arr.length; i++) {
        var data = arr[i];
//        core.log('Message:', data.type, i, arr.length, data.method);
//        if(data.messageID!=core.net.messageID){
//            console.info('Got a message not by number', data.messageID);
//        }
        if(data.type=='start-app'){
            //Start application
            core.net.doInIndicator();
            core.log('Starting app '+data.code, data.jsClass, data.description);
            core.startApplication(data.code, data.jsClass, data.name, data.description);
        }
        if(data.type=='error'){
            if(data.app){
                var app = core.jsApplications[data.app];
                if(app){
                    var addDialog = true;
                    for (var j = 0; j < core.desktop.dialogs.length; j++) {
                        if(core.desktop.dialogs[j].idError==data.errorCode){
                            addDialog = false;
                            break;
                        }
                    }
                    if(addDialog){
                        var dlg = app.showError(data.errorDescription);
                        dlg.idError = data.errorCode;
                    }
                }
            }
        }
        if(data.type=='enable'){
            var element = core.net.disables[data.disableIndex];
            if(element){
//                core.log('unmarkloading ', data.disableIndex, 'OK');
                element.unMarkLoading();
            }else{
//                core.log('unmarkloading ', data.disableIndex, 'Failed');
            }
            core.net.disables[data.disableIndex] = null;
        }
        if(data.type=='message'){
            core.net.doInIndicator();
            if(data.app && data.method){
                var app = core.jsApplications[data.app];
                var target = app;
                if(app && data.frame){
                    var frame = app.frames[data.frame];
                    if(frame)
                        target = frame;
//                    for (i = 0; i < app.frames.length; i++) {
//                        var frame = app.frames[i];
//                        if(frame.code==data.frame){
//                            target = frame;
//                        }
//                    }
                }
                if(target){
                    var method = target[data.method];
                    if(!method){
                        if(target.getMessageHandler){
                            var handler = target.getMessageHandler(data.method);
                            if(handler){
                                target = handler.object;
                                method = handler.method;
                            }
                        }
                    }
//                    core.log('Method is: '+data.method);
                    if(method){
                        try{
                            method.apply(target, [data.object]);
                        }catch(e){
                            core.log('Method', data.method, 'call failed');
                        }
                    }
                }else{
                    core.log('can\'t find method', data.method, 'of', data.app,
                            'frame:', data.frame);
            }
            }else{
                core.log('message: not enough data');
            }
        }
    }
    
};

core.net.startLink = function(){
    core.net.request('link?ts='+(new Date().getTime()), {
        token: core.net.token
    }, function(d){
//        try{
            var arr = $.makeArray(d);
//            core.log('Got new messages: '+arr.length);
            core.net.processIncomingMessages(arr);
//        }catch(ex){
//            core.log('There was an error processing messages :(');
//        }
        core.net.startLink();
    }, function(code, desc){
//        core.log('got link error: ['+code+']:', desc);
        if(code==1){
            //Session is over
//            core.log('Session is closed...');
            core.JSApplication.prototype.showError('Session is closed. Possible reasons are:<br/>'+
                'session terminated by server; '+
                'you have logged in from another location',
                'Connection terminated', function(){
                    window.location.reload();
                });
            core.net.acceptRequests = false;
        }else{
            core.setTimeout(core.net, core.net.startLink, 5000);
        }
    });
};
